﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Forms;
using Scommesse.Filters;
using Scommesse.Model;
using Scommesse.Persistence;
using Scommesse.Presenters.Adapters;
using Scommesse.Utility;
using Scommesse.View;
using System.Drawing;

namespace Scommesse.Presenters
{
    public class BasePresenter  : IBasePresenter
    {
        private readonly Dictionary<String, Quota> _carrelloController = new Dictionary<String, Quota>();
        private readonly Palinsesto _palinsesto;

        private readonly List<TreeNode> _treeNodeCarrello = new List<TreeNode>();
        //mi serve per verificare che non siano aggiunte due scommesse della stessa tipologia come 1 e 2 contemporaneamente

        private readonly Base _baseForm;
        private readonly InserimentoTessera _insForm;
        private readonly BetCard _betCard;
        private Carrello _carrello;

        public BasePresenter(BetCard betCard, AutenticazioneTessera autForm, InserimentoTessera insForm)
        {
            autForm.Close();
            _betCard = betCard;
            _palinsesto = Palinsesto.GetPalinsesto();
            _insForm = insForm;
            _baseForm = new Base();
            _carrello = new Carrello(betCard);
            _baseForm.AddListener(this);
            _baseForm.ShowDialog();
        }

        #region IBasePresenter Members

        public void RefreshImporto()
        {
            _baseForm.Importo = _carrello.Importo.ToString(CultureInfo.InvariantCulture);
        }

        public void RefreshMoltiplicatoreComplessivo()
        {
            _baseForm.MoltiplicatoreValue = _carrello.Moltiplicatore.ToString(CultureInfo.InvariantCulture);
        }

        public void RefreshVincitaPotenziale()
        {
            _carrello.Importo = _baseForm.Importo.Equals("") ? 0 : float.Parse(_baseForm.Importo);
            _baseForm.VincitaPotenziale = _carrello.TotaleVincita.ToString("c", new CultureInfo("it-IT"));
        }

        public void SetCredito()
        {
            _baseForm.CreditoEffettivo = _betCard.Credito.ToString("c", new CultureInfo("it-IT"));
        }

        public void PopulateTreeView(IEnumerable<IEntity> entities)
        {
            _baseForm.EventiTreeView.Nodes.Clear();
            Populate(_baseForm.EventiTreeView.Nodes, entities, 3);
            _baseForm.EventiTreeView.Sort();
            foreach (TreeNode node in _baseForm.EventiTreeView.Nodes)
            {
                node.Expand();
            }
        }

        public void Populate(TreeNodeCollection nodes, IEnumerable<IEntity> entities, int level)
        {
            if (level == 0)
                return;
            foreach (IEntity entity in entities)
            {
                TreeNode node = new TreeNode(entity.FullName);
                node.BackColor = entity.BackColor;
                node.ForeColor = entity.ForeColor;
                if (level == 3)
                {
                    node.NodeFont = entity.Font;
                }
                nodes.Add(node);
                if(entity is IComposite)
                Populate(node.Nodes, ((IComposite)entity).SubEntities, level - 1);
            }
        }
    
        public void PopulateMenuStrip(ToolStripItemCollection items,IEnumerable<IEntity> entities, int level)
        {
            if (level == 0)
                return;
            foreach (IEntity entity in entities)
            {
                ToolStripDropDownItem categoriaItem = new ToolStripMenuItem(entity.FullName);
                if (level == 2)
                {
                    categoriaItem.DropDownItemClicked += (_baseForm.categoriaItem_DropDownItemClicked);
                }
                items.Add(categoriaItem);
                if (entity is IComposite)
                    PopulateMenuStrip(categoriaItem.DropDownItems, ((IComposite)entity).SubEntities, level - 1);
            }
        }

        public void PopulateCategorieMenuStrip()
        {
            _baseForm.CategoriaMenuStrip.Items.Clear();
            List<IEntity> entities = new List<IEntity>();
            foreach (Categoria cat in _palinsesto.Categorie)
            {
                entities.Add(new CategoriaAdapter(cat));
            }
            PopulateMenuStrip(_baseForm.CategoriaMenuStrip.Items, entities, 2);
        }

        public void PopolateEventiList()
        {
            DateTime date = _baseForm.CalendarDate;
            List<IEvento> eventi = FiltroPalinsesto.GetAllEventiAtDate(
                FiltroPalinsesto.GetAllEventiByState(_palinsesto.GetAllEventi(), StatoEvento.Scommettibile), date);
            List<IEntity> entities = new List<IEntity>();
            foreach (Evento e in eventi)
            {
                entities.Add(new EventoAdapter(e,new Font("Verdana",9,FontStyle.Underline)));
            }
            PopulateTreeView(entities);
        }

        public void PopulateTreeViewByMenuStrip(ToolStripMenuItem clickedCompetizione)
        {
            List<IEvento> filteredEvents = FiltroPalinsesto.GetAllEventiByCompetizioneName(
                FiltroPalinsesto.GetAllEventiByCategoriaName(
                    FiltroPalinsesto.GetAllEventiByState(_palinsesto.GetAllEventi(), StatoEvento.Scommettibile),
                    clickedCompetizione.OwnerItem.Text), clickedCompetizione.Text);
            List<IEntity> entities = new List<IEntity>();
            foreach (Evento e in filteredEvents)
            {
                entities.Add(new EventoAdapter(e,new Font("Verdana",9,FontStyle.Underline)));
            }
            PopulateTreeView(entities);
        }

        public void PopulateTreeViewNextEvents()
        {
            List<IEvento> eventi = FiltroPalinsesto.GetAllEventiByState(_palinsesto.GetAllEventi(), StatoEvento.Scommettibile);
            List<IEntity> entities = new List<IEntity>();
            foreach (Evento e in eventi)
            {
                entities.Add(new EventoAdapter(e,new Font("Verdana",9,FontStyle.Underline)));
            }
            PopulateTreeView(entities);
        }

        public void PopulateTreeViewAllEvents()
        {
            List<IEvento> eventi = FiltroPalinsesto.GetAllEventiByState(_palinsesto.GetAllEventi(), StatoEvento.Scommettibile);
            List<IEntity> entities = new List<IEntity>();
            foreach (Evento e in eventi)
            {
                entities.Add(new EventoAdapter(e,new Font("Verdana",9,FontStyle.Underline)));
            }
            PopulateTreeView(entities);
        }

        public void SelezionaPuntata(TreeNode selectedNode)
        {
            
            if (selectedNode != null && selectedNode.Parent != null && selectedNode.Parent.Parent != null)
            {
                if (_treeNodeCarrello.Count != 0)
                {
                    foreach (TreeNode t in _treeNodeCarrello)
                    {
                        if (t.Parent.Parent.Text.Equals(selectedNode.Parent.Parent.Text))
                        {
                            String vecchioNome = t.Text+" - "+t.Parent.Parent.Text;
                            RemovePuntata(vecchioNome.Split('|')[0].Trim());
                            _baseForm.CarrelloListBox.Items.Remove(vecchioNome.Split('|')[0].Trim());
                            break;
                        }
                        
                    }
                }
                String nomeNode = selectedNode.Text + " - " + selectedNode.Parent.Parent.Text;
                if (!_carrelloController.ContainsKey(nomeNode))
                {
                    _baseForm.CarrelloListBox.Items.Add(
                        new CheckBox().Text = selectedNode.Text + " - " + selectedNode.Parent.Parent.Text.Split('|')[0].Trim());
                    _treeNodeCarrello.Add(selectedNode);

                    String str = selectedNode.Parent.Parent.Text;
                    var gma = new String[3];
                    gma = str.Split('|');
                    var cat = (Categoria) _palinsesto.GetCategoriaByName(gma[2].Trim());
                    var comp = cat.GetCompetizioneByName(gma[1].Trim());
                    String evento = gma[0];
                    var gma2 = new String[2];
                    gma2 = evento.Split('-');
                    String competitoreA = gma2[0].Trim();
                    var gma3 = new String[2];
                    gma3 = gma2[1].Split('@');
                    String competitoreB = gma3[0].Trim();

                    DateTime date = DateTime.Parse(gma3[1], new CultureInfo("it-IT", true));

                    IEvento e = comp.GetEvento(competitoreA, competitoreB, date);

                    var gmaQuota = new String[2];
                    gmaQuota = selectedNode.Text.Split(' ');
                    String risultato = gmaQuota[0];
                    String valore = gmaQuota[1];
                    var tip = StringValueAttribute.GetEnumByStringValueAttribute<Tipologia>(selectedNode.Parent.Text);
                    Quota q = e.GetQuotaByValore(risultato, tip);
                    if (_carrello == null)
                    {
                        _carrello = new Carrello(_betCard);
                    }
                    try
                    {
                        _carrello.AddPuntata(q);
                        _carrelloController.Add(nomeNode.Split('|')[0].Trim(), q);
                    }
                    catch(Exception exc)
                    {
                        MessageBox.Show("Impossibile inserire la puntata:\n" + exc.Message);
                        _treeNodeCarrello.Remove(selectedNode);
                        _baseForm.CarrelloListBox.Items.RemoveAt(_baseForm.CarrelloListBox.Items.Count-1);
                    }
                }
            }
        }

        public void RemovePuntata(String selectedItem)
        {
            var gma = selectedItem.Split('-');

            String testo = gma[0].Trim();
            foreach (TreeNode treeNode in _treeNodeCarrello)
            {
                if (treeNode.Text.Equals(testo))
                {
                    _treeNodeCarrello.Remove(treeNode);
                    break;
                }
            }
            _baseForm.CarrelloListBox.Items.Remove(_baseForm.CarrelloListBox.SelectedItem);
            _carrello.RemovePuntata(_carrelloController[selectedItem]);
            _carrelloController.Remove(selectedItem);
        }

        public void ConfermaScommessa()
        {
            try
            {
                float importoValue = float.Parse(_baseForm.Importo);
                if (importoValue >= 1)
                {
                    _baseForm.ImportoError = "";
                    _carrello.Importo = importoValue;
                    var controller = new ScommessaController(_betCard, _carrello);
                    controller.ControllaScommessa();

                    MessageBox.Show("Complimenti! La tua scommessa è stata registrata con successo!");
                        
                    SetCredito();
                    DataSaver.SaveBetCardOnFile(_betCard);
                    
                    // Genera un nuovo carrello vuoto
                    _carrello = new Carrello(_betCard);
                    RefreshImporto();
                    RefreshMoltiplicatoreComplessivo();
                    _carrelloController.Clear();
                    _treeNodeCarrello.Clear();
                    _baseForm.CarrelloListBox.Items.Clear();
                }
                else
                    _baseForm.ImportoError = "La puntata minima è di 1$";
            }
            catch (Exception e)
            {
                MessageBox.Show("Impossibile confermare la scommessa:\n"+e.Message);
            }
        }

        public void PopulateTreeViewByCategoria(String categoriaName)
        {
            List<IEvento> eventi = FiltroPalinsesto.GetAllEventiByCategoriaName(
                FiltroPalinsesto.GetAllEventiByState(_palinsesto.GetAllEventi(),StatoEvento.Scommettibile), categoriaName);
            List<IEntity> entities = new List<IEntity>();
            foreach(Evento e in eventi)
            {
                entities.Add(new EventoAdapter(e,new Font("Verdana",9,FontStyle.Underline)));
            }
            PopulateTreeView(entities);
        }

        public void LeTueScommesse()
        {
            new ScommessePresenter(_betCard);
        }

        public void RicaricaBetCard()
        {
            new RicaricaBetCardPresenter(_betCard);
        }

        public void CloseProgram()
        {
            _baseForm.Close();
            _insForm.Show();
        }

        #endregion
    }

}